/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.server.game;

import com.core.log.Debug;
import com.core.utils.Utils;

/**
 *
 * @author daz
 */
public class BacayTable extends GameTable {

    public static final int BA_CAY_NHAT = 1;
    public static final int BA_CAY_CHUONG = 2;
    private static final int NUMBER_BA_CAY_PLAYERS = 4;
    private static final int NUMBER_CARDS = 36;
    private static final int NUMBER_CARD_SHARE = 3;
    private int[] cardIds;
    public int playerIdCamChuong;
    public int maxPoints;
    public int[] sumCardPoints;
    public int gameResult[];
    public int[] markCard;
    private int numberPlayerOpenCard;

    public BacayTable(GameManager gameManager, GameRoom parent, long moneyBetDefault) {
        super(GameManager.BA_CAY, NUMBER_BA_CAY_PLAYERS, gameManager, parent, moneyBetDefault);
        cardIds = new int[NUMBER_CARDS];
        gameRule = BA_CAY_NHAT;
        sumCardPoints = new int[NUMBER_BA_CAY_PLAYERS];
        gameResult = new int[NUMBER_BA_CAY_PLAYERS];
        markCard = new int[10];

    }

    public void mergeCard() {
        cardIds = new int[36];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 4; j++) {
                cardIds[j * 9 + i] = j * 13 + i;
            }
        }
        for (int i = 0; i < 100; i++) {
            int tg = cardIds[i % NUMBER_CARDS];
            int randomNum = Utils.nextInt(36);
            cardIds[i % NUMBER_CARDS] = cardIds[randomNum];
            cardIds[randomNum] = tg;
        }
    }

    @Override
    public void startPlay() {
        isPlay = true;
        resetReadyState();
        mergeCard();
        shareCardBacay();
//        sendGameResult();
//        updateMoney();
    }

    private void updateMoney() {
        for (int i = 0; i < maxPlayersInMatch; i++) {
            if (listPlayer[i] != null) {
                if (gameResult[i] == 0) {
                    listPlayer[i].updateMoneyDelta(getMoneyWin(getNumberActivedPlayers()));
                    listPlayer[i].updateWin();
                } else {
                    long moneyChange = -getMoneyChange(gameResult[i], tableMoneyBet);
                    listPlayer[i].updateMoneyDelta(moneyChange);
                    listPlayer[i].updateLose();
                }
            }
        }
    }

    private void shareCardBacay() {
        StringBuilder msg = new StringBuilder();
        msg.append("S3C");

        for (int i = 0; i < maxPlayersInMatch; i++) {
            if (listPlayer[i] != null) {
                msg.append("|");
                int cardIndex = i * 3;
                msg.append(i);
                msg.append("|");
                msg.append(cardIds[cardIndex]);
                msg.append("|");
                msg.append(cardIds[cardIndex + 1]);
                msg.append("|");
                msg.append(cardIds[cardIndex + 2]);
            }

        }
        sendToAll(msg.toString());
    }

    private void calculateCardPoint() {
        for (int i = 0; i < maxPlayersInMatch; i++) {
            if (listPlayer[i] != null) {
                int index = i * 3;
                sumCardPoints[i] = cardIds[index] % 13 + cardIds[index + 1] % 13 + cardIds[index + 2] % 13 + 3;
                sumCardPoints[i] = (sumCardPoints[i] - 1) % 10 + 1;
            }
        }
    }

    private void sendGameResult() {
        calculateCardPoint();
        calculateResult();
        StringBuilder msg = new StringBuilder();
        msg.append("RS3");
        for (int i = 0; i < numberUsers; i++) {
            if (listPlayer[i] != null && i < maxPlayersInMatch) {
                msg.append("|");
                msg.append(i);
                msg.append("|");
                msg.append(gameResult[i]);
                msg.append("|");
                msg.append(sumCardPoints[i]);
            }
        }
        sendToAll(msg.toString());
    }

    private void calculateResult() {
        for (int i = 0; i < maxPlayersInMatch; i++) {
            gameResult[i] = 0;
        }
        for (int i = 0; i < maxPlayersInMatch; i++) {
            for (int j = 0; j < maxPlayersInMatch; j++) {
                if (listPlayer[i] != null) {
                    if (sumCardPoints[i] < sumCardPoints[j] && i != j) {
                        gameResult[i]++;
                    } else if (sumCardPoints[i] == sumCardPoints[j] && i != j) {
                        int cardIndex1 = i * 3;
                        int cardIndex2 = j * 3;
                        int[] cardCheck = {cardIds[cardIndex1], cardIds[cardIndex1 + 1], cardIds[cardIndex1 + 2],
                            cardIds[cardIndex2], cardIds[cardIndex2 + 1], cardIds[cardIndex2 + 2]};
                        findBestCard(cardCheck);
                        gameResult[i]++;
                        if (markCard[0] == 0) {
                            gameResult[i]--;
                        }

                    }
                }
            }
        }
    }

    private void findBestCard(int[] cardCheck) {
        int arrLength = cardCheck.length;
        for (int i = 0; i < arrLength; i++) {
            if (i < 3) {
                markCard[i] = 0;
            } else {
                markCard[i] = 1;
            }

        }
        for (int i = 0; i < arrLength - 1; i++) {
            for (int j = i; j < arrLength; j++) {
                if (cardCheck[i] / 26 != 2 && cardCheck[j] / 26 == 2) {
                    swapArr(cardCheck, i, j);
                    swapArr(markCard, i, j);
                } else if (cardCheck[i] / 26 == 2 && cardCheck[j] / 26 == 2) {
                    if (cardCheck[i] % 13 < cardCheck[j] % 13) {
                        swapArr(cardCheck, i, j);
                        swapArr(markCard, i, j);
                    }
                } else if (cardCheck[i] / 26 != 2 && cardCheck[j] / 26 != 2) {
                    if (cardCheck[i] / 13 < cardCheck[j] / 13) {
                        swapArr(cardCheck, i, j);
                        swapArr(markCard, i, j);
                    } else if (cardCheck[i] / 13 == cardCheck[j] / 13) {
                        if (cardCheck[i] % 13 < cardCheck[j] % 13) {
                            swapArr(cardCheck, i, j);
                            swapArr(markCard, i, j);
                        }
                    }
                }

            }
        }

    }

    private void swapArr(int[] valueArr, int index1, int index2) {
        int tg = valueArr[index1];
        valueArr[index1] = valueArr[index2];
        valueArr[index2] = tg;
    }

    public void sendGameRule() {
        StringBuilder msg = new StringBuilder();
        msg.append("GM");
        msg.append("|");
        if (gameRule == BA_CAY_CHUONG) {
            msg.append(1);
            msg.append("|");
            msg.append(playerIdCamChuong);
        } else {
            msg.append(0);
        }
        sendToAll(msg.toString());
    }

    public void sendMoneyChange() {
        int numberActive = getNumberActivedPlayers();
        for (int i = 0; i < maxPlayersInMatch; i++) {
            if (listPlayer[i] != null) {
                if (gameResult[i] == 0) {
                    sendToAll("CM" + "|" + i + "|" + getMoneyWin(numberActive));
                } else {
                    sendToAll("CM" + "|" + i + "|-" + getMoneyChange(gameResult[i], tableMoneyBet));
                }
            }
        }
        sendToAll("FCM|");
    }

    private synchronized void processFnMessage() {
        numberPlayerOpenCard++;
        if (numberPlayerOpenCard >= getNumberActivedPlayers()) {
            sendGameResult();
            sendMoneyChange();
            updateMoney();
            resetGame();
        }
    }

    @Override
    public void processMessage(String request, int playerId) {
        super.processMessage(request, playerId);
        String[] message = Utils.split(request, '|');
        if (message[0].equals("OB")) {
            //OB|playerId|stt bai
            sendToAll(request);
            return;
        }
        if (message[0].equals("FN")) {
            processFnMessage();
            return;
        }
        if (message[0].startsWith("CT")) {
//            resetTable();
//            sendListPlayer();
//            sendMoneyInfo();
//            sendReadyState();
            return;
        }
    }

    private long getMoneyWin(int numberPlayer) {
        switch (numberPlayer) {
            case 2:
                return (tableMoneyBet * 9 / 10);
            case 3:
                return (tableMoneyBet * 3 * 9 / 10);
            case 4:
                return (tableMoneyBet * 6 * 9 / 10);

        }
        return 0;
    }

    private long getMoneyChange(int result, long moneyBet) {
        switch (result) {
            case 1:
                return (moneyBet);
            case 2:
                return (moneyBet * 2);
            case 3:
                return (moneyBet * 3);
        }
        return 0;
    }

    @Override
    public void sendGameInfo() {
        sendGameRule();
    }

    @Override
    protected void resetGame() {
        numberPlayerOpenCard = 0;
        resetTable();
    }
}
